package com.wanakiko.impldetails.interceptor;

import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.Iterator;

/* MyBatis中的责任链模式 */
public class ChainOfResponsibility {

    public static void main(String[] args) {
        Interceptor1st interceptor1st = new Interceptor1st();
        Interceptor2nd interceptor2nd = new Interceptor2nd();
        /* 需求：在2号拦截器处执行拦截，其后的代码不执行 */
        Interceptor3rd interceptor3rd = new Interceptor3rd();
        InterceptorChain interceptorChain = new InterceptorChain();
        interceptorChain.addInterceptor(interceptor1st);
        interceptorChain.addInterceptor(interceptor2nd);
        interceptorChain.addInterceptor(interceptor3rd);
        interceptorChain.plugin(new Object());
    }

}

/* 拦截器责任链 */
class InterceptorChain {

    private final ArrayList<Interceptor> interceptorArrayList = Lists.newArrayList();
    /* 提取ArrayList迭代器预防java.lang.StackOverflowError */
    private Iterator<Interceptor> iterator;

    public void addInterceptor(Interceptor interceptor) {
        interceptorArrayList.add(interceptor);
    }

    public Object plugin(Object target) {
        /* 仅执行单次ArrayList的初始化，预防java.util.ConcurrentModificationException */
        if (iterator == null) {
            iterator = interceptorArrayList.iterator();
        }
        if (iterator.hasNext()) {
            Interceptor item = iterator.next();
            item.plugin(target, this); /* this表示调用当前拦截器 */
        }
        return target;
    }

    public Object pluginAll(Object target) {
        for (Interceptor interceptor : interceptorArrayList) {
            target = interceptor.plugin(target, this); /* this表示调用当前拦截器 */
        }
        return target;
    }

}

/* 拦截器-3 */
class Interceptor3rd implements Interceptor {
    @Override
    public Object plugin(Object target, InterceptorChain chain) {
        System.out.println("execute Interceptor3rd...");
        return target;
    }
}

/* 拦截器-2 */
class Interceptor2nd implements Interceptor {
    @Override
    public Object plugin(Object target, InterceptorChain chain) {
        System.out.println("execute Interceptor2nd...");
        return target; /* 如果在此处定义chain.plugin(target);表示执行到拦截器3后停止程序 */
    }
}

/* 拦截器-1 */
class Interceptor1st implements Interceptor {
    @Override
    public Object plugin(Object target, InterceptorChain chain) {
        System.out.println("execute Interceptor1st...");
        return chain.plugin(target); /* 执行到拦截器2后停止程序 */
    }
}

/* 拦截器接口 */
interface Interceptor {
    Object plugin(Object target, InterceptorChain chain);
}
